#![no_std]
#![no_main]



use defmt_rtt as _;

#[cfg(feature = "app")]
use embedded_alloc::LlffHeap;

#[cfg(feature = "app")]
use mlibs::cmsis_rtos2::kernel::{os_kernel_initialize, os_kernel_start};

use mlibs::cmsis_rtos2::kernel::system_init;

#[cfg(feature = "app")]
use mlibs::cmsis_rtos2::utils::AlignStore;

use mlibs::cortex_m_rt;
use mlibs::periph::flash;
use mlibs as _;

#[cfg(feature = "app")]
use task::app_task;
use utils::OtaInfo;

#[cfg(feature = "app")]
extern crate alloc;

#[cfg(feature = "app")]
mod service;

mod error;

#[cfg(feature = "app")]
mod task;


mod driver;

mod utils;

#[cfg(feature = "app")]
mod proto;

#[cfg(feature = "app")]
#[global_allocator]
static HEAP: LlffHeap = LlffHeap::empty();

#[cfg(feature = "app")]
unsafe fn heap_init() {
    const HEAP_SIZE: usize = 1024 * 5;
    static HEAP_MEM: AlignStore<HEAP_SIZE> = AlignStore::const_new();
    HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE);
}

const BOOT_ORIGIN: u32 = 0x08000000;
const BOOT_LENGTH: u32 = 8 * 1024;

const APP_ORIGIN: u32 = BOOT_ORIGIN + BOOT_LENGTH;
const APP_LENGTH: u32 = 24 * 1024;

const OTA_ORIGIN: u32 = APP_ORIGIN + APP_LENGTH;

#[cfg(feature = "app")]
#[cortex_m_rt::entry]
unsafe fn main() -> ! {
    system_init();

    defmt::println!("app start");

    heap_init();
    os_kernel_initialize();
    app_task::start();
    os_kernel_start();
    loop {}
}


fn run_app_param() {
    defmt::println!("start boot param");
    if !OtaInfo.verify() {
        return;
    }
    defmt::println!("boot param");
    _ = flash::erase(OtaInfo.app_addr, OtaInfo.pkg_size);
    _ = flash::write(OtaInfo.app_addr, OtaInfo.ota_addr as _, OtaInfo.pkg_size);
    OtaInfo.destroy();
}

#[cfg(feature = "boot")]
#[cortex_m_rt::entry]
unsafe fn main() -> ! {
    use utils::bootload_with_disable_irq;
    system_init();

    run_app_param();

    bootload_with_disable_irq(APP_ORIGIN);
    loop {}
}



